package jp.sourceforge.akjrcp.flvtools.explorer;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import jp.sourceforge.akjrcp.akj_betas.Akj_betasPlugin;
import jp.sourceforge.akjrcp.akj_betas.FilePlayer;
import jp.sourceforge.akjrcp.akj_betas.Messages;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegUI;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegUtils;
import jp.sourceforge.akjrcp.flvtools.basic.AVISettingPage;
import jp.sourceforge.akjrcp.flvtools.basic.FLVToolsPage;
import jp.sourceforge.akjrcp.flvtools.basic.MPEGSettingPage;
import jp.sourceforge.akjrcp.flvtools.basic.OpenDirectable;
import jp.sourceforge.akjrcp.flvtools.basic.SimpleView;
import jp.sourceforge.akjrcp.flvtools.basic.WMVSettingPage;
import jp.sourceforge.akjrcp.ui.DirectoryList;
import jp.sourceforge.akjrcp.util.DropFileListener;
import jp.sourceforge.akjrcp.util.DropFileMonitor;
import jp.sourceforge.akjrcp.util.FLVChecker;
import jp.sourceforge.akjrcp.commons.util.FileNameUtils;
import jp.sourceforge.akjrcp.util.image.ImageUtils;
import jp.sourceforge.akjrcp.youtubedl.YoutubeDLListener;
import jp.sourceforge.akjrcp.youtubedl.YoutubeDLView;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.draw2d.FlowLayout;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.InputEvent;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.LayoutManager;
import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.MarginBorder;
import org.eclipse.draw2d.Panel;
import org.eclipse.draw2d.StackLayout;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.WorkbenchWindow;
import org.eclipse.ui.part.ViewPart;

/**
 * This sample class demonstrates how to plug-in a new workbench view. The view
 * shows data obtained from the model. The sample creates a dummy model on the
 * fly, but a real implementation would connect to the model available either in
 * this or another plug-in (e.g. the workspace). The view is connected to the
 * model using a content provider.
 * <p>
 * The view uses a label provider to define how model objects should be
 * presented in the view. Each view can present the same model objects using
 * different labels and icons, if needed. Alternatively, a single label provider
 * can be shared between views in order to ensure that objects of the same type
 * are presented in the same way everywhere.
 * <p>
 */

public class ExplorerView extends ViewPart implements OpenDirectable,FFMpegExecutable,MonitorCancelable {
	public static Log log = LogFactory.getLog(ExplorerView.class);
	
	public static final String ID = ExplorerView.class.getName();
	public static final String SORT_TYPE="explorer.sorttype";

	// private ScrolledComposite scroll;

	private String currentDir;

	private String[] assistantNames;

	//private Text directoryPath;
	private CCombo directoryPaths;
	private ExplorerPathChange explorerPathChange;
	static{
		log.info(Messages.getString("explorer.no_support"));
	}
	protected static Image noFFMpegImage = new Image(Display.getCurrent(),
			DirectoryList.class.getClassLoader().getResourceAsStream(
					"jp/sourceforge/akjrcp/flvtools/resource/"+Messages.getString("explorer.no_ffmpeg")));
	
	protected static Image noSupportImage = new Image(Display.getCurrent(),
			DirectoryList.class.getClassLoader().getResourceAsStream(
					"jp/sourceforge/akjrcp/flvtools/resource/"+Messages.getString("explorer.no_support")));
	
	protected static Image loadingImage = new Image(Display.getCurrent(),
			DirectoryList.class.getClassLoader().getResourceAsStream(
					"jp/sourceforge/akjrcp/flvtools/resource/loading.png"));;

	protected static Image moveUpPrevImage = new Image(Display.getCurrent(),
			DirectoryList.class.getClassLoader().getResourceAsStream(
					"jp/sourceforge/akjrcp/flvtools/resource/moveup_prev.png"));;

	protected static Image folderImage = new Image(Display.getCurrent(),
			DirectoryList.class.getClassLoader().getResourceAsStream(
					"jp/sourceforge/akjrcp/flvtools/resource/folder_large.png"));;

	private File currentFile = null;

	private boolean firstPaint = true;
	
	ConvertingMonitorDialog convertingDialog;

	
	private FFMpegExplorerExecuter ffmpegExecuter;
	
	private int sortType;
	public static final int SORT_A_Z=0;
	public static final int SORT_Z_A=1;
	public static final int SORT_NEW=2;
	public static final int SORT_OLD=3;
	public static final int SORT_BIG=4;
	public static final int SORT_SMALL=5;
	
	private FLVChecker flvChecker=new FLVChecker();
	
	private String oldPath;
	
	public void initAssistantName(File file) {
		
		String list[] = file.list();//list must be checked.
		if(list==null){
			log.info("secyrity problem:"+file.getAbsolutePath());
			assistantNames=new String[0];
			return;
		}
		
		FLVFilter filter = new FLVFilter();
		ArrayList tmpNames = new ArrayList();
		if(list!=null){
		for (int i = 0; i < list.length; i++) {
			File tmp = new File(file, list[i]);
			if (tmp.isDirectory()) {
				String flvList[] = tmp.list(filter);
				if(flvList!=null){
				for (int j = 0; j < flvList.length; j++) {
					String flvKey = trimNumberName(flvList[j].substring(0,
							flvList[j].length() - ".flv".length()));
					tmpNames.remove(flvKey);
					tmpNames.add(flvKey);
				}
				}
			}
		}
		}
		assistantNames = (String[]) tmpNames.toArray(new String[0]);
	}

	public class ImageLoader implements Runnable {
		ArrayList list = new ArrayList();

		public void run() {
			Object[] figure_file = list.toArray();
			Display display=getSite().getShell().getDisplay();
			//
			boolean ffmpegAvailable=FFMpegUI.isFFMpegOrPureFFMpegAvailable(FFMpegUI.getFFmpegOrPureFFMpeg());
			
			for (int i = 0; i < figure_file.length; i++) {
				Object th_file[] = (Object[]) figure_file[i];
				ThumbnailFigure figure = (ThumbnailFigure) th_file[0];
				Image img = null;
				if(ffmpegAvailable){
				img=ThumbnailManager.loadThumbnail((File) th_file[1],
						noSupportImage);
				}else{
					img=noFFMpegImage;
				}
				if(getSite()!=null && getSite().getShell()!=null){//for after quit
				if (getSite().getShell().getDisplay() != null) {
					display.asyncExec(new SetImage(img, figure));
					
				} else {
					log.warn("display null");
				}
				}
			}

		}

		public void add(ThumbnailFigure figure, File file) {
			list.add(new Object[] { figure, file });
		}
	}

	public class SetImage implements Runnable {
		Image img;

		ThumbnailFigure figure;

		public SetImage(Image img, ThumbnailFigure figure) {
			this.img = img;
			this.figure = figure;
		}

		public void run() {
			figure.setImage(img);
		}
	}

	private String trimNumberName(String name) {
		String newName = name;
		if (name.endsWith(")")) {
			int x = name.lastIndexOf("(");
			if (x != -1) {
				String digi = name.substring(x + 1, name.length() - 1);
				boolean isDigit = true;
				for (int i = 0; i < digi.length(); i++) {
					if (!Character.isDigit(digi.charAt(i))) {
						isDigit = false;
						break;
					}
				}
				if (isDigit) {
					newName = name.substring(0, x);
				}
			}
		}
		return newName;
	}

	public class FLVFilter implements FilenameFilter {

		public boolean accept(File arg0, String arg1) {
			return arg1.toLowerCase().endsWith(".flv");
		}

	}

	public class MoveAction extends Thread {
		public void run() {
			//
			ActionValues[] values = (ActionValues[]) actionValueList
					.toArray(new ActionValues[0]);
			for (int i = 0; i < values.length; i++) {
				values[i].setEnabled(false);
			}

			for (int i = 0; i < values.length; i++) {
				execMove(values[i]);
			}

			openDirectory(currentDir);
			//
		}

		private void execMove(ActionValues values) {
			File parent = values.getFile().getParentFile();
			String path = parent.getAbsolutePath();
			String dir = values.getNewDirectory();
			if (dir.length() > 0) {
				path += "\\" + dir;
			}
			path += "\\" + trim(values.getNewName());
			path += ".flv";

			if (!values.getFile().getAbsolutePath().equals(path)) {
				log.info("rename to:" + path);
				File renameFile = new File(path);

				File emptyName = getEmptyFileName(renameFile);
				boolean result = values.getFile().renameTo(emptyName);
				if (!result) {
					log.warn("rename faild:" + emptyName.getAbsolutePath());
				}
			}
		}

		private String trim(String name) {
			if (name.toLowerCase().endsWith(".flv")) {
				name = name.substring(0, name.length() - 4);
			}
			return name;
		}
	}

	
	private void updateExplorerPaths() {
		String paths=Akj_betasPlugin.getDefault().getPreferenceStore().getString(FLVToolsPage.EXPLORER_PATHS);
		String path[]=paths.split(";");//one day should change for other platform.
		directoryPaths.removeAll();
		
		for (int i = 0; i < path.length; i++) {
			directoryPaths.add(path[i]);
		}
		
		directoryPaths.removeSelectionListener(explorerPathChange);
		
		if(currentDir==null){
			directoryPaths.select(0);
		}else{
			boolean find=false;
			for (int i = 0; i < path.length; i++) {
				if(path[i].equals(currentDir)){
					directoryPaths.select(i);
					find=true;
					break;
				}
			}
			if(!find){
				directoryPaths.add(currentDir);
				directoryPaths.select(directoryPaths.getItemCount()-1);
			}
		}
		
		directoryPaths.addSelectionListener(explorerPathChange);
		
		updateMovePathsMenus();
	}
	
	public class SettingMonitor2 implements org.eclipse.jface.util.IPropertyChangeListener {

		public void propertyChange(org.eclipse.jface.util.PropertyChangeEvent event) {
			if (event.getProperty().equals(FFMpegUI.FFMPEG_PATH)) {
					ffmpegEnableChanged(FFMpegUI.getFFmpeg(),FFMpegUI.getPureFFmpeg());
					reload();//for thumbnail
				}else if (event.getProperty().equals(FFMpegUI.PURE_FFMPEG_PATH)) {
					ffmpegEnableChanged(FFMpegUI.getFFmpeg(),FFMpegUI.getPureFFmpeg());
					reload();//for thumbnail
				} 
			
		}
		
	}
	public class SettingMonitor implements IPropertyChangeListener {

		public void propertyChange(PropertyChangeEvent event) {
			log.info(event.getProperty());
			if (event.getProperty().equals(FLVToolsPage.EXPLORER_PATHS)) {
				updateExplorerPaths();
			}else if(event.getProperty().equals(FLVToolsPage.FLVTOOL2_PATH)) {
				//synch setting.
				enableseek.setEnabled(isEnableFLVTool2());
				
			}else{
				String settins[]={AVISettingPage.AVI_AUDIO_CODEC,AVISettingPage.AVI_VIDEO_CODEC,MPEGSettingPage.MPEG_AUDIO_CODEC,WMVSettingPage.WMV_AUDIO_CODEC};
				for (int i = 0; i < settins.length; i++) {
					if(event.getProperty().equals(settins[i])){
						ffmpegEnableChanged(FFMpegUI.getFFmpeg(),FFMpegUI.getPureFFmpeg());
						break;
					}
				}
			}
		}

		

	}

	public void ffmpegEnableChanged(String ffmpeg,String pureffmpeg) {
		//more detaild.
		if(ffmpeg==null && pureffmpeg==null){
		convert.setEnabled(false);
		}else{
		convert.setEnabled(true);
		if(ffmpeg==null){
			pspMenuItem.setEnabled(false);
			mp3MenuItem.setEnabled(false);
			
			//depends on settings.
			aviMenuItem.setEnabled(FFMpegExplorerExecuter.canPureFFMpeg("avi"));
			mpegMenuItem.setEnabled(FFMpegExplorerExecuter.canPureFFMpeg("mpg"));
			wmvMenuItem.setEnabled(FFMpegExplorerExecuter.canPureFFMpeg("wmv"));
			}
		else{
			pspMenuItem.setEnabled(true);
			wmvMenuItem.setEnabled(true);
			mp3MenuItem.setEnabled(true);
			aviMenuItem.setEnabled(true);
			mpegMenuItem.setEnabled(true);
			}
		}
	}

	public static File getEmptyFileName(File file) {
		if (!file.exists()) {
			return file;
		} else {
			String fileName = file.getName();
			String head = fileName;
			int e = fileName.lastIndexOf(".");
			String ext = "";
			if (e != -1) {
				ext = fileName.substring(e);
				head = fileName.substring(0, e);
			}
			int index = 1;
			File newFile = null;
			while (newFile == null || newFile.exists()) {
				String newName = head + "(" + index + ")" + ext;
				// log.info("newName:"+newName);
				newFile = new File(file.getParentFile(), newName);
				index++;
			}
			return newFile;
		}
	}
	
	public class ExplorerPathChange implements SelectionListener {

		public void widgetSelected(SelectionEvent e) {
			String dir=directoryPaths.getItem(directoryPaths.getSelectionIndex());
			openDirectory(dir);
			canvas.forceFocus();
		}

		public void widgetDefaultSelected(SelectionEvent e) {
			
		}

	}
	

	public class ExecExecuter implements SelectionListener {

		public void widgetSelected(SelectionEvent e) {
			PlatformUI.getWorkbench().getDisplay().syncExec(new MoveAction());
			// Shell shell=new
			// Shell(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
			// shell.setVisible(true);
			// shell.setText("log");

		}

		public void widgetDefaultSelected(SelectionEvent e) {
			// TODO Auto-generated method stub

		}

	}

	/**
	 * The constructor.
	 */
	ExplorerView self;

	private MenuItem moveDirs;
	public ExplorerView() {
		self=this;
	}

	/**
	 * This is a callback that will allow us to create the viewer and initialize
	 * it.
	 */

	public String findBaseDir() {
		String baseDir = SimpleView.findBaseDir();
		return baseDir;
	}

	public void createPartControl(Composite root) {

		ThumbnailManager.clearThumbnails();

		root.setLayout(new GridLayout(1, false));

		Composite controler = new Composite(root, SWT.NULL);
		controler.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		controler.setLayout(new GridLayout(3, false));
		Button reloadButton = new Button(controler, SWT.NULL);
		reloadButton.setText(Messages.getString("reload"));
		reloadButton.addSelectionListener(new SelectionListener() {

			public void widgetSelected(SelectionEvent e) {
				reload();
			}

			public void widgetDefaultSelected(SelectionEvent e) {
				// TODO Auto-generated method stub

			}

		});

		// execButton.addSelectionListener(new ExecExecuter());
		//change ccombo
		//directoryPath = new Text(controler, SWT.SINGLE | SWT.READ_ONLY);
		directoryPaths=new CCombo(controler,SWT.READ_ONLY);
		explorerPathChange=new ExplorerPathChange();
		
		GridData datax = new GridData(GridData.FILL_HORIZONTAL);
		directoryPaths.setLayoutData(datax);
		
		CCombo st=new CCombo(controler,SWT.READ_ONLY);
		st.add(Messages.getString("sort.az"));
		st.add(Messages.getString("sort.za"));
		st.add(Messages.getString("sort.new"));
		st.add(Messages.getString("sort.old"));
		st.add(Messages.getString("sort.big"));
		st.add(Messages.getString("sort.small"));
		sortType=Akj_betasPlugin.getDefault().getPreferenceStore().getInt(SORT_TYPE);;
		st.select(sortType);
		
		st.addSelectionListener(new SelectionListener(){

			public void widgetDefaultSelected(SelectionEvent e) {
				
			}

			public void widgetSelected(SelectionEvent e) {
				sortType=((CCombo)(e.getSource())).getSelectionIndex();
				Akj_betasPlugin.getDefault().getPreferenceStore().setValue(SORT_TYPE, sortType);
				reload();
			}
			
		});
		
		canvas = new FigureCanvas(root);
		canvas.setLayoutData(new GridData(GridData.FILL_BOTH));
		
		rootFigure = new Figure();
		canvas.setContents(rootFigure);
		canvas.addKeyListener(new KeyListener(){

			public void keyPressed(KeyEvent e) {
				
			}

			public void keyReleased(KeyEvent e) {
				log.info(e);
				if(e.stateMask == SWT.CTRL && e.keyCode==97){
					//log.infose");
					selectAllThumbnail();
				}
			}
			
		});

		rootFigure.setLayoutManager(new StackLayout());
		/*
		 * Panel sc=new Panel(); rootFigure.add(sc);
		 * sc.setBackgroundColor(org.eclipse.draw2d.ColorConstants.orange);
		 * sc.setLayoutManager(new FlowLayout(false));
		 */

		canvas.addControlListener(new ResizeMonitor(rootFigure));

		canvasPopup = new Menu(canvas);
		canvas.setMenu(canvasPopup);
		MenuItem player = new MenuItem(canvasPopup, SWT.CASCADE);
		player.setText(Messages.getString("explorer.play"));
		Menu playMenu = new Menu(player);

		player.setMenu(playMenu);

		MenuItem systemPlayItem = new MenuItem(playMenu, SWT.PUSH);
		systemPlayItem.setText(Messages.getString("explorer.System-Player"));

		systemPlayItem.addSelectionListener(new SelectionListener() {

			public void widgetSelected(SelectionEvent e) {
				if(currentFile!=null && currentFile.isFile()){
					FilePlayer.play(currentFile, "flv");
				}
			}

			public void widgetDefaultSelected(SelectionEvent e) {
				// TODO Auto-generated method stub

			}

		});

		MenuItem flowPlayItem = new MenuItem(playMenu, SWT.PUSH);
		flowPlayItem.setText(Messages.getString("explorer.flowPlayer"));

		flowPlayItem.addSelectionListener(new SelectionListener() {

			public void widgetSelected(SelectionEvent e) {
				playFlowPlayer(currentFile);
			}

			public void widgetDefaultSelected(SelectionEvent e) {
				// TODO Auto-generated method stub

			}

		});

		
		convert = new MenuItem(canvasPopup, SWT.CASCADE);
		convert.setText(Messages.getString("explorer.convert"));
		Menu convertMenu = new Menu(convert);
		convert.setMenu(convertMenu);

		
		
		MenuItem movie = new MenuItem(convertMenu, SWT.CASCADE);
		movie.setText(Messages.getString("explorer.movie"));
		Menu movieMenu = new Menu(movie);
		movie.setMenu(movieMenu);

		
		pspMenuItem = new MenuItem(movieMenu, SWT.PUSH);
		pspMenuItem.setText(Messages.getString("explorer.psp"));
		pspMenuItem.addSelectionListener(new SelectionListener() {
			

			public void widgetSelected(SelectionEvent e) {
				ffmpegExecuter = new FFMpegExplorerExecuter(self);
				ffmpegExecuter.setExtension("psp");//something special
				setExportBaseDir(ffmpegExecuter);
				ffmpegExecuter.setConvertingFile(toSelectionFiles());
				ffmpegExecuter.startExecute();
			}
			
			public void widgetDefaultSelected(SelectionEvent e) {

			}

		});
		
		mpegMenuItem = new MenuItem(movieMenu, SWT.PUSH);
		mpegMenuItem.setText(Messages.getString("explorer.mpeg"));
		mpegMenuItem.addSelectionListener(new SelectionListener() {
			

			public void widgetSelected(SelectionEvent e) {
				ffmpegExecuter = new FFMpegExplorerExecuter(self);
				ffmpegExecuter.setExtension("mpg");
				setExportBaseDir(ffmpegExecuter);
				ffmpegExecuter.setConvertingFile(toSelectionFiles());
				ffmpegExecuter.startExecute();
			}
			
			public void widgetDefaultSelected(SelectionEvent e) {

			}

		});
		
		wmvMenuItem = new MenuItem(movieMenu, SWT.PUSH);
		wmvMenuItem.setText(Messages.getString("explorer.wmv"));
		wmvMenuItem.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {
				
				ffmpegExecuter = new FFMpegExplorerExecuter(self);
				ffmpegExecuter.setExtension("wmv");
				setExportBaseDir(ffmpegExecuter);
				ffmpegExecuter.setConvertingFile(toSelectionFiles());
				ffmpegExecuter.startExecute();
			}

			public void widgetDefaultSelected(SelectionEvent e) {

			}

		});
		aviMenuItem = new MenuItem(movieMenu, SWT.PUSH);
		aviMenuItem.setText(Messages.getString("explorer.avi"));
		aviMenuItem.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {
				ffmpegExecuter = new FFMpegExplorerExecuter(self);
				ffmpegExecuter.setExtension("avi");
				
				setExportBaseDir(ffmpegExecuter);
				ffmpegExecuter.setConvertingFile(toSelectionFiles());
				ffmpegExecuter.startExecute();
			}

			public void widgetDefaultSelected(SelectionEvent e) {

			}

		});
		
		//audio
		MenuItem audio = new MenuItem(convertMenu, SWT.CASCADE);
		audio.setText(Messages.getString("explorer.audio"));
		Menu audioMenu = new Menu(audio);
		audio.setMenu(audioMenu);


		mp3MenuItem = new MenuItem(audioMenu, SWT.PUSH);
		mp3MenuItem.setText(Messages.getString("explorer.mp3"));
		mp3MenuItem.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {
				ffmpegExecuter = new FFMpegExplorerExecuter(self);
				ffmpegExecuter.setExtension("mp3");
				setExportBaseDir(ffmpegExecuter);
				ffmpegExecuter.setConvertingFile(toSelectionFiles());
				ffmpegExecuter.startExecute();
			}

			public void widgetDefaultSelected(SelectionEvent e) {

			}

		});
		
		/*
		MenuItem mp3_direct = new MenuItem(audioMenu, SWT.PUSH);
		mp3_direct.setText(Messages.getString("explorer.mp3_direct"));
		mp3_direct.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {

			}

			public void widgetDefaultSelected(SelectionEvent e) {

			}

		});
		*/
		
		wavMenuItem = new MenuItem(audioMenu, SWT.PUSH);
		wavMenuItem.setText(Messages.getString("explorer.wav"));
		wavMenuItem.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {
				ffmpegExecuter = new FFMpegExplorerExecuter(self);
				ffmpegExecuter.setExtension("wav");
				setExportBaseDir(ffmpegExecuter);
				ffmpegExecuter.setConvertingFile(toSelectionFiles());
				ffmpegExecuter.startExecute();
			}

			public void widgetDefaultSelected(SelectionEvent e) {

			}

		});
		
		
		//image
		MenuItem image = new MenuItem(convertMenu, SWT.CASCADE);
		image.setText(Messages.getString("explorer.image"));
		Menu imageMenu = new Menu(image);
		image.setMenu(imageMenu);

		
	
		
		MenuItem jpeg = new MenuItem(imageMenu, SWT.PUSH);
		jpeg.setText(Messages.getString("explorer.jpeg"));
		jpeg.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {
				ffmpegExecuter = new FFMpegExplorerExecuter(self);
				ffmpegExecuter.setExtension("jpg");
				setExportBaseDir(ffmpegExecuter);
				ffmpegExecuter.setConvertingFile(toSelectionFiles());
				ffmpegExecuter.startExecute();
			}

			public void widgetDefaultSelected(SelectionEvent e) {

			}

		});
		MenuItem png = new MenuItem(imageMenu, SWT.PUSH);
		png.setText(Messages.getString("explorer.png"));
		png.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {
				ffmpegExecuter = new FFMpegExplorerExecuter(self);
				ffmpegExecuter.setExtension("png");
				setExportBaseDir(ffmpegExecuter);
				ffmpegExecuter.setConvertingFile(toSelectionFiles());
				ffmpegExecuter.startExecute();
			}

			public void widgetDefaultSelected(SelectionEvent e) {

			}

		});
		
		
		MenuItem makeThumbnail = new MenuItem(canvasPopup, SWT.PUSH);
		makeThumbnail.setText(Messages.getString("explorer.makeThumbnail"));
		makeThumbnail.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {
				
				File files[]=toSelectionFiles();
				if(files.length>0){
				Shell shell=new Shell(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
				shell.setText("hello");
				shell.setSize(660,480);
				ThumnailPreviewWindow dialog=new ThumnailPreviewWindow(shell,files[0].getAbsolutePath());
				
				dialog.open();
				}
			}

			public void widgetDefaultSelected(SelectionEvent e) {

			}

		});
		
		
		
		
		/*
		 * some ffmpeg make problem
		MenuItem gif = new MenuItem(imageMenu, SWT.PUSH);
		gif.setText(Messages.getString("explorer.gif"));
		gif.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {
				ffmpegExecuter = new FFMpegFileExecuter(self);
				ffmpegExecuter.setExtension("gif");
				ffmpegExecuter.setConvertingFile(toSelectionFiles());
				ffmpegExecuter.startExecute();
			}

			public void widgetDefaultSelected(SelectionEvent e) {

			}

		});
		*/
		
//		 ffmpeg available.
		ffmpegEnableChanged(Akj_betasPlugin.getDefault()
				.getFFmpeg(),Akj_betasPlugin.getDefault()
						.getPureFFmpeg());
		
		
		MenuItem sep1=new MenuItem(canvasPopup,SWT.SEPARATOR);
		
		moveDirs = new MenuItem(canvasPopup, SWT.CASCADE);
		
		
		movePaths = new MenuItem(canvasPopup, SWT.CASCADE);
		updateMovePathsMenus();
		
		
		//moveDir = new MenuItem(canvasPopup, SWT.CASCADE);
		updateMoveDirsMenus(new String[0]);
		
		
		MenuItem sep2=new MenuItem(canvasPopup,SWT.SEPARATOR);

		/*
		 * TODO futre.
		MenuItem extractFile = new MenuItem(canvasPopup, SWT.PUSH);
		extractFile.setText(Messages.getString("explorer.extract_file"));
		extractFile.addSelectionListener(new SelectionListener() {

			public void widgetSelected(SelectionEvent e) {
				extractFile();
			}

			public void widgetDefaultSelected(SelectionEvent e) {
				// TODO Auto-generated method stub

			}

		});
		*/
		
		renameFile = new MenuItem(canvasPopup, SWT.PUSH);
		renameFile.setText(Messages.getString("explorer.rename_file"));
		renameFile.addSelectionListener(new SelectionListener() {

			public void widgetSelected(SelectionEvent e) {
				renameFile();
			}

			public void widgetDefaultSelected(SelectionEvent e) {
				// TODO Auto-generated method stub

			}

		});
		
		enableseek = new MenuItem(canvasPopup, SWT.PUSH);
		enableseek.setText(Messages.getString("enable_seek"));
		enableseek.setEnabled(isEnableFLVTool2());
		enableseek.addSelectionListener(new SelectionListener() {

			public void widgetSelected(SelectionEvent e) {
				callFLVTool2();
			}

			public void widgetDefaultSelected(SelectionEvent e) {
				// TODO Auto-generated method stub

			}

		});
		
		
		
		MenuItem sep3=new MenuItem(canvasPopup,SWT.SEPARATOR);
		
		MenuItem selectAll = new MenuItem(canvasPopup, SWT.PUSH);
		selectAll.setText(Messages.getString("explorer.select_all"));
		selectAll.addSelectionListener(new SelectionListener() {

			public void widgetSelected(SelectionEvent e) {
				selectAllThumbnail();
			}

			public void widgetDefaultSelected(SelectionEvent e) {
				// TODO Auto-generated method stub

			}

		});
		MenuItem sep4=new MenuItem(canvasPopup,SWT.SEPARATOR);
		
		MenuItem openDir = new MenuItem(canvasPopup, SWT.PUSH);
		openDir.setText(Messages.getString("explorer.open_dir"));
		openDir.addSelectionListener(new SelectionListener() {

			public void widgetSelected(SelectionEvent e) {
				openFolder();
			}

			public void widgetDefaultSelected(SelectionEvent e) {
				// TODO Auto-generated method stub

			}

		});
		
		
		root.addPaintListener(new PaintListener() {

			public void paintControl(PaintEvent e) {
				if (firstPaint) {
					firstPaint = false;
					openDirectory(findBaseDir());// initial call

				}
			}

		});

		
		  //For D&D
		   
		   DropFileMonitor monitor=new DropFileMonitor(canvas,new DropOpen());
		  
		   
		//

		//
		// for
		// scroll

		/*
		 * 
		 * Composite controler=new Composite(root,SWT.NULL);
		 * controler.setLayout(new GridLayout(2,false)); Button execButton=new
		 * Button(controler,SWT.NULL);
		 * execButton.setText(Messages.getString("execute"));
		 * execButton.addSelectionListener(new ExecExecuter());
		 * directoryPath=new Text(controler,SWT.SINGLE|SWT.READ_ONLY); GridData
		 * datax=new GridData(GridData.FILL_HORIZONTAL);
		 * directoryPath.setLayoutData(datax);
		 * 
		 * Composite cp=new Composite(root,SWT.NULL); GridData data=new
		 * GridData(GridData.FILL_BOTH); cp.setLayoutData(data);
		 * 
		 * cp.setBackground(new Color(Display.getCurrent(),255,0,0));
		 * cp.setLayout(new FillLayout());
		 * 
		 * scroll = new ScrolledComposite (cp,SWT.H_SCROLL | SWT.V_SCROLL);
		 * parent = new Composite(scroll,SWT.NULL); //parent.setBackground(new
		 * Color(Display.getCurrent(),0,255,0)); parent.setLayout(new
		 * GridLayout(1,false));
		 * 
		 * 
		 * String baseDir=findBaseDir();
		 * 
		 * openDirectory(baseDir);
		 * 
		 * parent.addControlListener(new ControlAdapter(){ public void
		 * controlResized(ControlEvent e) {
		 * //scroll.setMinSize(parent.getSize());
		 * //parent.setSize(320,130*parent.getChildren().length); } });
		 * 
		 * scroll.setContent(parent); log.info(root.getSize());
		 * 
		 * //log.info(""+130*parent.getChildren().length);
		 * //parent.setSize(320,140*parent.getChildren().length);
		 * 
		 * scroll.setExpandHorizontal(true); scroll.setExpandVertical(true);
		 * 
		 */
		// hookContextMenu();
		// contributeToActionBars();
		
		 
		Akj_betasPlugin.getDefault().getPluginPreferences().addPropertyChangeListener( new SettingMonitor());
		PlatformUI.getPreferenceStore().addPropertyChangeListener( new SettingMonitor2());
		//
		try{
		YoutubeDLView.youtubeDLListeners.add(new YoutubeDownloaded());
		}catch(Exception e){
			log.warn(e);
		}
	}

	public void openFolder(){
		if(currentFile==null){
			return;
		}
		File dir;
		if(currentFile.isDirectory()){
			dir=currentFile;
		}else{
			dir=currentFile.getParentFile();
		}
		Runtime r=Runtime.getRuntime();
		try {
			r.exec(new String[]{"explorer",dir.getAbsolutePath()});
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	private void updateMoveDirsMenus(String[] dirs) {
		if(moveDirMenu!=null){
			moveDirMenu.dispose();
		}
		moveDirMenu = new Menu(movePaths);
		moveDirs.setMenu(moveDirMenu);
		
		moveDirs.setText(Messages.getString("explorer.move_dirs"));
		
		for (int i = 0; i < dirs.length; i++) {
			MenuItem movePath = new MenuItem(moveDirMenu, SWT.PUSH);
			movePath.setText(dirs[i]);
			movePath.addSelectionListener(new MoveFLVToDir(currentDir+"\\"+dirs[i]));
		}
	}

	public class MoveFLVToDir implements SelectionListener{
		private String dir;
		public MoveFLVToDir(String path){
			this.dir=path;
		}
		public void widgetDefaultSelected(SelectionEvent e) {
			
		}

		public void widgetSelected(SelectionEvent e) {
			moveDirectory(dir);//TODO;
		}
		
	}
	
	public void updateMovePathsMenus(){
		if(movePathMenu!=null){
			movePathMenu.dispose();
		}
		movePathMenu = new Menu(movePaths);
		movePaths.setMenu(movePathMenu);
		
		movePaths.setText(Messages.getString("explorer.move_paths"));
		String paths=Akj_betasPlugin.getDefault().getPreferenceStore().getString(FLVToolsPage.EXPLORER_PATHS);
		String path[]=paths.split(";");//one day should change for other platform.
		for (int i = 0; i < path.length; i++) {
			MenuItem movePath = new MenuItem(movePathMenu, SWT.PUSH);
			movePath.setText(new File(path[i]).getName());
			movePath.addSelectionListener(new MoveFLVToDir(path[i]));
		}
	}
	
	public void moveDirectory(String path){
		File selectFile[]=toSelectionFiles();
		for (int i = 0; i < selectFile.length; i++) {
			File newFile=new File(path+"\\"+selectFile[i].getName());
			String renameFile=FileNameUtils.getChangedExtensionName(newFile, "flv");
			
			boolean result=selectFile[i].renameTo(new File(renameFile));
			if(!result){
				log.warn("move faild: from "+selectFile[i]+" to "+renameFile);
			}
		}
		reload();
		//for(int i=0;i<)
		//FileNameUtils
	}
	public void reload(){
		log.info("reload:"+currentDir);
		openDirectory(currentDir);
		canvas.forceFocus();
	}
	public void renameFile(){
		RenameDialog dialog=new RenameDialog(self.getSite());
		dialog.setFiles(toSelectionFiles());
		dialog.open();
		int returncode=dialog.getReturnCode();
		
		//rename internally when ok button is pressed.
		if(returncode==0){
			reload();
		}
		
	}
	private File[] toSelectionFiles() {
		ThumbnailFigure[] figures=explorerFigure.getSelectionThumbnails();
		File file[]=new File[figures.length];
		for (int i = 0; i < file.length; i++) {
		file[i]=figures[i].toFile();
		}
		return file;
	}
	
	private boolean isEnableFLVTool2(){
		
		String path = Akj_betasPlugin.getDefault().getPreferenceStore()
				.getString(FLVToolsPage.FLVTOOL2_PATH);
		if (path.endsWith("flvtool2.exe")) {
			File exe=new File(path);
			if(exe.exists()){
				return true;
			}
		}
	
	return false;
	}
	public void callFLVTool2() {
		Runtime runtime = Runtime.getRuntime();
		String path = Akj_betasPlugin.getDefault().getPreferenceStore()
				.getString(FLVToolsPage.FLVTOOL2_PATH);
		if (path.endsWith("flvtool2.exe")) {
			File file = new File(path);
			if (file.exists()) {
				String[] args;
				if (path.indexOf("akj_friends") != -1) {
					args = new String[] { path, "-U",
							currentFile.getAbsolutePath() };
				} else {
					args = new String[] { path, "u",
							currentFile.getAbsolutePath() };
				}
				try {
					WorkbenchWindow workbenchWindow = (WorkbenchWindow) PlatformUI
							.getWorkbench().getActiveWorkbenchWindow();

					IProgressMonitor convertMonitor = workbenchWindow
							.getStatusLineManager().getProgressMonitor();
					// getSite().getShell().getDisplay().syncExec(new
					// SetProgressMonitor(convertMonitor,"flvtool2:"+currentFile.getName(),1));
					Process p = runtime.exec(args);
					/*
					 * ProcessMonitor monitor=new ProcessMonitor(p);
					 * monitor.startMonitor();
					 */
					try {
						p.waitFor();
						// log.infodone");
						convertMonitor.done();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}

	}

	public class DoneProgressMonitor implements Runnable {
		IProgressMonitor monitor;

		public DoneProgressMonitor(IProgressMonitor monitor) {
			this.monitor = monitor;

		}

		public void run() {
			monitor.done();
		}
	}

	public class SetProgressMonitor implements Runnable {
		IProgressMonitor monitor;

		String text;

		int step;

		public SetProgressMonitor(IProgressMonitor monitor, String text,
				int step) {
			this.monitor = monitor;
			this.text = text;
			this.step = step;
		}

		public void run() {
			monitor.beginTask(text, step);
			
		}
	}

	/*
	public class MoveUpFigure extends Panel {
		Label titleLabel;

		Label imageLabel;

		public void setImage(Image img) {
			if (img != null) {
				imageLabel.setIcon(img);
			} else {
				log.info("setimage:" + getLabel());
			}
		}

		public String getLabel() {
			return titleLabel.getText();
		}

		public void setLabel(String text) {
			titleLabel.setText(text);
		}

		public MoveUpFigure(String label, Image img) {
			super();
			this.setLayoutManager(new FlowLayout(false));
			imageLabel = new Label(img);
			imageLabel.setToolTip(new Label(label));
			add(imageLabel);
			titleLabel = new Label(label);
			add(titleLabel);
			
			imageLabel.setToolTip(new Label(Messages
					.getString("moveup_directory")));
			
			this.setBorder(new MarginBorder(2));
			
			addMouseListener(new org.eclipse.draw2d.MouseListener() {

				public void mousePressed(org.eclipse.draw2d.MouseEvent arg0) {
				}

				public void mouseReleased(org.eclipse.draw2d.MouseEvent arg0) {
					// TODO Auto-generated method stub

				}

				public void mouseDoubleClicked(
						org.eclipse.draw2d.MouseEvent arg0) {
					String path = new File(currentDir).getParent();
					log.info(path);
					openDirectory(path);
				}

			});
		}
	}*/
	
	public class MoveUpPrevNextFigure extends Panel {
		Label titleLabel;

		Label imageLabel;

		public void setImage(Image img) {
			if (img != null) {
				imageLabel.setIcon(img);
			} else {
				log.info("setimage:" + getLabel());
			}
		}

		public String getLabel() {
			return titleLabel.getText();
		}

		public void setLabel(String text) {
			titleLabel.setText(text);
		}

		public MoveUpPrevNextFigure(String label, Image img) {
			super();
			this.setLayoutManager(new FlowLayout(false));
			imageLabel = new Label(img);
			imageLabel.setToolTip(new Label(label));
			add(imageLabel);
			titleLabel = new Label(label);
			add(titleLabel);
			
			imageLabel.setToolTip(new Label(Messages
					.getString("moveup_directory")));
			
			this.setBorder(new MarginBorder(2));
			
			addMouseListener(new org.eclipse.draw2d.MouseListener() {

				public void mousePressed(org.eclipse.draw2d.MouseEvent arg0) {
				}

				public void mouseReleased(org.eclipse.draw2d.MouseEvent arg0) {
					// TODO Auto-generated method stub

				}

				public void mouseDoubleClicked(
						org.eclipse.draw2d.MouseEvent event) {
					//log.info(event.x+","+event.y);
					if(event.y<60){
					String path = new File(currentDir).getParent();
					log.info(path);
					openDirectory(path);
					}else{
						if(event.x<80){
							//prev
							openPrev();
						}else{
							//next
							openPrev();
						}
					}
				}

			});
		}
	}
	
	/*
	 * check if folder has flv files
	 */
	public class FolderThumbnailChecker extends Thread{
		public FolderThumbnailChecker(String dir){
			targetDir=dir;
		}
		private String targetDir;
		public void run(){
			List list=explorerFigure.getChildren();
			List dirNames=new ArrayList();
			for (int i = 0; i < list.size(); i++) {
				if(targetDir.equals(currentDir)){
					if(list.get(i) instanceof FolderFigure){
						
						FolderFigure ffigure=(FolderFigure)list.get(i);
						String dirName=ffigure.realName;
						File dir=new File(targetDir+"\\"+dirName);
						
						String[] first=dir.list();
						if(first==null){
							first=new String[0];
						}
						FIND_IMAGE:for (int j = 0; j < first.length; j++) {
							if(first[j].toLowerCase().endsWith(".flv") && new File(dir,first[j]).length()>1024){//valid flv
								//log.info(dir+","+first[j]);
								Image img = ThumbnailManager.loadThumbnail(new File(dir,first[j]),
										noFFMpegImage);
								
								Image thumb=ImageUtils.createThumbnail(img, 120, 90);
								//img.dispose();
								
								PlatformUI.getWorkbench().getDisplay().syncExec(new SetLabelExec(ffigure.getThumnailLabel(),thumb));
								dirNames.add(dirName);
								break FIND_IMAGE;
							}
						}
						
					}
				}else{
					//if folder changed finish it.
					break;
				}
			}
			PlatformUI.getWorkbench().getDisplay().asyncExec(new UpdateMoveDirsMenu((String[]) dirNames.toArray(new String[0])));
			
			
			log.info("done,folderCheck:"+targetDir);
		}
	}
	
	public class UpdateMoveDirsMenu extends Thread{
		private String[] dirs;
		public UpdateMoveDirsMenu(String[] dirs){
			this.dirs=dirs;
		}
		public void run(){
			updateMoveDirsMenus(dirs);
		}
	}
	
	public class SetLabelExec extends Thread{
		private Label label;
		private Image icon;
		public SetLabelExec(Label label,Image icon){
			this.label=label;
			this.icon=icon;
		}
		public void run(){
			label.setIcon(icon);
		}
	}

	
	public class FolderFigure extends Panel {
		private String realName;
		Label titleLabel;

		Label imageLabel;

		
		
		private Label thumnailLabel;
		public Label getThumnailLabel() {
			return thumnailLabel;
		}
		public void setThumnailLabel(Label thumnailLabel) {
			this.thumnailLabel = thumnailLabel;
		}
		public void setSelection(boolean bool){
			
		}
		public void setImage(Image img) {
			if (img != null) {
				imageLabel.setIcon(img);
			} else {
				log.info("setimage:" + getLabel());
			}
		}

		public String getLabel() {
			return titleLabel.getText();
		}

		public void setLabel(String text) {
			titleLabel.setText(text);
		}

		public FolderFigure(String label, Image img) {
			super();
			realName=label;
			this.setLayoutManager(new FlowLayout(false));
			imageLabel = new Label(img);
			imageLabel.setToolTip(new Label(label));
			add(imageLabel);
			titleLabel = new Label(trimTitle(label));
			add(titleLabel);

			
			thumnailLabel=new Label();
			thumnailLabel.setBorder(new MarginBorder(1));
			imageLabel.setLayoutManager(new StackLayout());
			imageLabel.add(thumnailLabel);
			
			this.setBorder(new MarginBorder(2));
			
			addMouseListener(new org.eclipse.draw2d.MouseListener() {

				public void mousePressed(org.eclipse.draw2d.MouseEvent arg0) {
				}

				public void mouseReleased(org.eclipse.draw2d.MouseEvent arg0) {
					
					currentFile = new File(currentDir, realName);//to open directory
				}

				public void mouseDoubleClicked(
						org.eclipse.draw2d.MouseEvent arg0) {
					File dir = new File(currentDir, realName);
					openDirectory(dir.getAbsolutePath());
				}

			});
		}
		public String trimTitle(String name) {
			return name.substring(0, Math.min(16, name.length()));
		}
	}

	
	public static class Explorer extends Panel{
		public ThumbnailFigure[] getSelectionThumbnails(){
			List list=new ArrayList();
			Figure figures[]=(Figure[]) this.getChildren().toArray(new Figure[0]);
			//log.infofigures:"+figures.length);
			for (int i = 0; i < figures.length; i++) {
				if(figures[i] instanceof ThumbnailFigure){
					
					if(((ThumbnailFigure)figures[i]).isSelection()){
					list.add(figures[i]);
					}
				
				}
			}
			return (ThumbnailFigure[]) list.toArray(new ThumbnailFigure[0]);
		}
	}
	
	public void setExportBaseDir(FFMpegExplorerExecuter executer){
		boolean isSame=Akj_betasPlugin.getDefault().getPreferenceStore().getBoolean(FLVToolsPage.EXPORT_SAME_DIRECTORY);
		String path=Akj_betasPlugin.getDefault().getPreferenceStore().getString(FLVToolsPage.EXPORT_DIRECTORY);
		
		if(!isSame &&path.length()>0){
			executer.setExportBaseDir(new File(path));
		}
	}
	
	public   class ThumbnailFigure extends Panel {
		Label titleLabel;

		Label imageLabel;

		boolean hasExtension = true;

		
		boolean selection;
		
		LineBorder lineBorder; 
		MarginBorder marginBorder;
		
		private String realName;
		
		private String extension="flv";
		public String trimTitle(String name) {
			return name.substring(0, Math.min(16, name.length()));
		}
		
		public void setSelection(boolean bool){
			if(this.selection!=bool){
			this.selection=bool;
			if(selection){
				
				this.setBorder(lineBorder);
			}else{
				this.setBorder(marginBorder);
			}
			repaint();
			}
		}
		public boolean isSelection(){
			return selection;
		}
		public void turnSelection(){
			setSelection(!selection);
		}
		public void setImage(Image img) {
			if (img != null) {
				imageLabel.setIcon(img);
			} else {
				log.info("setimage:" + getLabel());
			}
		}

		public String getLabel() {
			return titleLabel.getText();
		}

		public void setLabel(String text) {
			titleLabel.setText(text);
		}

		public File toFile() {
			if (isHasExtension()) {
				return new File(currentDir, realName
						+ "."+extension);
			} else {
				return new File(currentDir, realName);
			}

		}
		
		public ThumbnailFigure(String label, Image img) {
			super();
			realName=label;//bug fix for 
			this.setLayoutManager(new FlowLayout(false));
			imageLabel = new Label(img);
			imageLabel.setToolTip(new Label(toTooltip(realName)));
			add(imageLabel);
			titleLabel = new Label(trimTitle(label));
			add(titleLabel);
			addMouseListener(new org.eclipse.draw2d.MouseListener() {

			

				public void mousePressed(org.eclipse.draw2d.MouseEvent mouseEvent) {
					File selectFirst=currentFile;
					currentFile = toFile();//for play.
					log.trace("currentFile:" + currentFile);
					enableseek.setEnabled(isEnableFLVTool2());
					
					if(mouseEvent.button==1){//left click
					if((mouseEvent.getState() & InputEvent.CONTROL)>0){
						turnSelection();
					}else if((mouseEvent.getState() & InputEvent.SHIFT)>0){
						//
						selectBetween(selectFirst,currentFile);
					}else{
						unselectAll();
						turnSelection();
					}
					}else if(mouseEvent.button==3){//right click
						if(toSelectionFiles().length==0){
							//now ignore right click
							//setSelection(true);
						}
					}
					
				}

				public void mouseReleased(org.eclipse.draw2d.MouseEvent arg0) {
					// TODO Auto-generated method stub

				}

				public void mouseDoubleClicked(
						org.eclipse.draw2d.MouseEvent arg0) {
					playFile(toFile());

				}

			});
			
			
			lineBorder = new LineBorder();
			lineBorder.setColor(ColorConstants.green);
			lineBorder.setWidth(2);
			
			marginBorder=new MarginBorder(2);
			this.setBorder(marginBorder);

		}
		
		
		
		public String toTooltip(String path){
			String ext="";
			if(hasExtension){
				ext="."+extension;
			}
			File file=new File(currentDir,path+ext);
			
			String type=extension.toUpperCase();
			if(type.equals("")){//EMPTY only FLV
				type="FLV";//
			}
			String label="("+type+")"+path;
			long length=file.length();
			label+="\n\n";
			if(length>0){
				label+=FFMpegUtils.toLabeledByte(length)+"\n";
			}
			
			label+=new Date(file.lastModified()).toLocaleString();//TODO change someday
			return label;
		}
		
		public void unselectAll(){
			
			Figure figures[]=(Figure[]) this.getParent().getChildren().toArray(new Figure[0]);
			//log.infofigures:"+figures.length);
			for (int i = 0; i < figures.length; i++) {
				if(figures[i] instanceof ThumbnailFigure){
					//log.infounselect");
					if(figures[i]!=this){
					((ThumbnailFigure)figures[i]).setSelection(false);
					}
				}
			}
		}

		public void selectAll(){
			
			Figure figures[]=(Figure[]) this.getParent().getChildren().toArray(new Figure[0]);
			//log.infofigures:"+figures.length);
			for (int i = 0; i < figures.length; i++) {
				if(figures[i] instanceof ThumbnailFigure){
					//log.infounselect");
					//if(figures[i]!=this){
					((ThumbnailFigure)figures[i]).setSelection(true);
				//	}
				}
			}
		}

		public boolean isHasExtension() {
			return hasExtension;
		}

		public void setHasExtension(boolean hasExtension) {
			this.hasExtension = hasExtension;
		}

		public String getExtension() {
			return extension;
		}

		public void setExtension(String extension) {
			this.extension = extension;
			imageLabel.setToolTip(new Label(toTooltip(realName)));//reset
		}
	}
	
	public void selectAllThumbnail(){
		
		Figure figures[]=(Figure[]) explorerFigure.getChildren().toArray(new Figure[0]);
		//log.infofigures:"+figures.length);
		for (int i = 0; i < figures.length; i++) {
			if(figures[i] instanceof ThumbnailFigure){
				//log.infounselect");
				//if(figures[i]!=this){
				((ThumbnailFigure)figures[i]).setSelection(true);
			//	}
			}
		}
	}
	
	public void selectBetween(File file1,File file2){
		log.info("between:"+file1+","+file2);
		if(file1.getAbsolutePath().equals(file2.getAbsolutePath())){
			//same do nothing.
			return;
		}
		List list=explorerFigure.getChildren();
		int f1=-1;
		int f2=-1;
		for(int i=0;i<list.size();i++){
			if(list.get(i) instanceof ThumbnailFigure){
				ThumbnailFigure th=(ThumbnailFigure)list.get(i);
				if(file1.getAbsolutePath().equals(th.toFile().getAbsolutePath())){
					f1=i;
				}else if(file2.getAbsolutePath().equals(th.toFile().getAbsolutePath())){
					f2=i;
				}
			}
		}
		
		if(f1<0 || f2<0){
			log.warn("faild select");
		}else{
			log.info("f1="+f1+",f2="+f2);
		}
		if(f1<f2){
			for(int i=f1+1;i<=f2;i++){//f1 is already select
				((ThumbnailFigure)list.get(i)).turnSelection();
			}
		}else{
			for(int i=f1-1;i>=f2;i--){//f1 is already select
				((ThumbnailFigure)list.get(i)).turnSelection();
			}
		}
		
		
		
	}

	public void playFile(File file) {
		log.info("playFile:" + file);
		boolean primaryFlowPlayer = Akj_betasPlugin.getDefault()
				.getPreferenceStore().getBoolean(
						FLVToolsPage.PRIMARY_FLOWPLAYER);
		if (primaryFlowPlayer) {
			playFlowPlayer(file);
		} else {
			if (!FilePlayer.play(file)) {
				playFlowPlayer(file);
			}
		}
	}

	public void playFlowPlayer(File file) {
		if (isFLVExtension(file)) {
			if (flowPlayerShell == null
					|| flowPlayerShell.getShell().isDisposed()) {
				flowPlayerShell = new FlowPlayerShell(this.getSite().getShell());
			}
			flowPlayerShell.openFLVFile(file);
		}
	}

	public boolean isFLVExtension(File file) {
		return file.getName().toLowerCase().endsWith(".flv");
	}
/*
 * Use it.
 * root - stacklayout
 * explorer -customFlowLayout(root)
 */
	public static class CustomFlowLayout implements LayoutManager {
		Figure parentFigure;
		FigureCanvas canvas;
		
		public CustomFlowLayout(FigureCanvas canvas,Figure control) {
			this.parentFigure = control;
			this.canvas=canvas;
		}

		public Object getConstraint(IFigure child) {
			// TODO Auto-generated method stub
			return null;
		}

		public Dimension getMinimumSize(IFigure container, int wHint, int hHint) {
			// log.info(container+" minimumsize:"+"whint="+wHint+"
			// hHint="+hHint);
			// log.infoparent:"+control.getSize());
			return getPreferredSize(container, wHint, hHint);
		}

		/*
		 * return figure bound of figure
		 * (�� Javadoc)
		 * @see org.eclipse.draw2d.LayoutManager#getPreferredSize(org.eclipse.draw2d.IFigure, int, int)
		 */
		public Dimension getPreferredSize(IFigure container, int wHint,
				int hHint) {
			// log.info(container+" preferedsize:"+"whint="+wHint+"
			// hHint="+hHint);
			// log.infoparent:"+control.getSize());
			layout(container);
			Figure figures[] = (Figure[]) container.getChildren().toArray(
					new Figure[0]);
			int my = 0;
			for (int i = 0; i < figures.length; i++) {
				my = Math.max(my, figures[i].getLocation().y
						+ figures[i].getSize().height);

			}
			// log.infomy="+my);
			return new Dimension(parentFigure.getClientArea().x+padding*2, my+padding*2);
		}

		public void invalidate() {
			// log.infoinvalidate");
		}
		int padding=2;
		public void layout(IFigure container) {
			Figure figures[] = (Figure[]) container.getChildren().toArray(
					new Figure[0]);
			int margin = 1;//margin
			
			int dx = padding;
			int dy = padding;
			int lastYPosition = 0;
			
			if (parentFigure.getSize().width == 0 && parentFigure.getSize().height == 0) {
				return;
			}
			
			for (int i = 0; i < figures.length; i++) {
				Dimension d = figures[i].getPreferredSize();
				if (dx == padding) {
					figures[i].setLocation(new Point(dx, dy));
					figures[i].setSize(d.width, d.height);
					dx += d.width + margin;
					lastYPosition = d.height + margin;
				} else {
					
					int sc = 0;
					if (!canvas.getVerticalBar().isEnabled()) {
						sc = 16;	//set scrollbar size
					}
					
					if (dx + d.width > parentFigure.getClientArea().width - sc) {// over w
						dx = padding;
						dy += lastYPosition;
					}
					figures[i].setLocation(new Point(dx, dy));
					figures[i].setSize(d.width, d.height);
					dx += d.width + margin;
					lastYPosition = d.height + margin;
				}

			}
			/*
			int my = 0;
			for (int i = 0; i < figures.length; i++) {
				my = Math.max(my, figures[i].getLocation().y
						+ figures[i].getSize().height);

			}
			*/
			
		}

		public void remove(IFigure child) {

		}

		public void setConstraint(IFigure child, Object constraint) {
			// TODO Auto-generated method stub

		}

	}

	public class ResizeMonitor implements ControlListener {
		Figure figure;

		public ResizeMonitor(Figure figure) {
			this.figure = figure;
		}

		public void controlMoved(ControlEvent e) {

		}

		public void controlResized(ControlEvent e) {
			// FigureCanvas source=(FigureCanvas)e.getSource();
			figure.revalidate();// i don't know.i have any other idea.
			//
		}

	}

	public void showConvertingStatus(){
		
			convertingDialog=new ConvertingMonitorDialog(self.getSite());
			convertingDialog.setCancelable(this);
			if(ffmpegExecuter!=null){
				log.info(""+executingIndex);
				convertingDialog.setFileList(ffmpegExecuter.getFileList());
				convertingDialog.selectFile(executingIndex);
			}
			
			convertingDialog.open();
		
	}
	
	public void openPrev(){
		if(oldPath!=null){
			openDirectory(oldPath);
		}
	}
	

	
	public void openDirectory(String path) {
		if(oldPath==null){
			oldPath=currentDir;
		}else{
			if(!currentDir.equals(oldPath)){
				oldPath=currentDir;
			}
		}
		clearList();//clear first
		if(path.endsWith("res"))return;
		//return;
		long debug=System.currentTimeMillis();
		log.info("path:" + path);
		//directoryPath.setText(path);
		currentDir = path;
		updateExplorerPaths();
		File file = new File(path);
		initAssistantName(file);//what is this?
		initFolder(file);
	
		initList(file);
		long listTime=(System.currentTimeMillis()-debug)/1000;
		
		updatePopupMenu(file);

		// confirm rename
		String flvaddmode=Akj_betasPlugin.getDefault().getPreferenceStore().getString(FLVToolsPage.FLV_EXTENSION_ADD);
		
		if (!isEveryFLVOK(file) && !flvaddmode.equals(FLVToolsPage.FLV_EXTENSION_ADD_NEVER)) {
			int dialog_button=0;//open for auto
			if(flvaddmode.equals(FLVToolsPage.FLV_EXTENSION_ADD_DIALOG)){
			MessageDialog dialog = new MessageDialog(this.getSite().getShell(),
					Messages.getString("confirm_rename"), null, Messages
							.getString("confirm_rename_message"),
					MessageDialog.INFORMATION,
					new String[] { "OK", "Cancell" }, 0);// default select is ok. 0.4.1

			dialog_button= dialog.open();
			}
			log.info("dialog:" + dialog_button);
			if (dialog_button == 0) {
				String flvs[] = getFLVFiles(file);
				for (int i = 0; i < flvs.length; i++) {
					if (!flvs[i].toLowerCase().endsWith(".flv")) {
						File flv = new File(flvs[i]);
						File newFile = new File(FileNameUtils
								.getChangedExtensionName(flv, "flv"));
						boolean result = flv.renameTo(newFile);
						log.info("result:" + result + " " + newFile);

					}

				}
				initList(file);// for redraw
			}
		}
		
		FolderThumbnailChecker checker=new FolderThumbnailChecker(currentDir);
		checker.start();

		//Akj_betasPlugin.getDefault().getProcessPrinter().printError("");
	}

	Menu canvasPopup;

	private long MIN_FLV_SIZE=1024;

	public void updatePopupMenu(File file) {
		//
	}

	public boolean isEveryFLVOK(File file) {
		String files[] = getFLVFiles(file);
		for (int i = 0; i < files.length; i++) {
			if (!files[i].toLowerCase().endsWith(".flv")) {
				return false;
			}
		}
		return true;
	}

	
	private boolean isFLVFile(File file){
		if(file.isDirectory()){
			return false;
		}
		if(file.length()<MIN_FLV_SIZE){
			return false;
		}
		if(file.getName().toLowerCase().endsWith(".flv")){
			
			return true;
		}
		
		if(file.getName().indexOf(".")!=-1){
			return false;
		}else{
			boolean b=flvChecker.checkFLV(file);//keep result;
			if(b){
				log.info(file.getAbsolutePath());
			}
			return b;
		}
	}
	
	public String[] getFLVFiles(File baseDir) {
		String list[] = baseDir.list();
		if(list==null){
			list=new String[0];
		}
		// parent.setLayout(new RowLayout());
		ArrayList array = new ArrayList();
		for (int i = 0; i < list.length; i++) {
			File file2 = new File(baseDir, list[i]);

			if (isFLVFile(file2)) {
				array.add(file2);
			}
		}
		File[] files=(File[]) array.toArray(new File[0]);
		FLVListComparator comparator=new FLVListComparator();
		Arrays.sort(files,comparator);
		String paths[]=new String[files.length];
		for (int i = 0; i < paths.length; i++) {
			paths[i]=files[i].getAbsolutePath();
		}
		return paths;
	}
	
	//TODO support mix.
	public String[] getExtensionFiles(File baseDir,String extensions[]) {
		String list[] = baseDir.list();
		if(list==null){
			list=new String[0];
		}
		// parent.setLayout(new RowLayout());
		ArrayList array = new ArrayList();
		for (int i = 0; i < list.length; i++) {
			File file2 = new File(baseDir, list[i]);

			for (int j = 0; j < extensions.length; j++) {
				if(file2.getName().toLowerCase().endsWith("."+extensions[j])){
					array.add(file2);
				}
			}
		}
		File[] files=(File[]) array.toArray(new File[0]);
		FLVListComparator comparator=new FLVListComparator();
		Arrays.sort(files,comparator);
		String paths[]=new String[files.length];
		for (int i = 0; i < paths.length; i++) {
			paths[i]=files[i].getAbsolutePath();
		}
		return paths;
	}

	public class FLVListComparator implements Comparator{

		public int compare(Object arg0, Object arg1) {
			File file1=(File) arg0;
			File file2=(File) arg1;
			if(sortType==SORT_A_Z){
				return file1.getName().compareTo(file2.getName());
			}if(sortType==SORT_Z_A){
				return file1.getName().compareTo(file2.getName())*-1;
			}else if(sortType==SORT_NEW){
				long v=file1.lastModified() - file2.lastModified();
				if(v>1){
					return -1;
				}else if(v<1){
					return 1;
				}else{
					return 0;
				}
			}else if(sortType==SORT_OLD){
				long v=file1.lastModified() - file2.lastModified();
				if(v>1){
					return 1;
				}else if(v<1){
					return -1;
				}else{
					return 0;
				}
			}else if(sortType==SORT_BIG){
				long v=file1.length() - file2.length();
				if(v>1){
					return -1;
				}else if(v<1){
					return 1;
				}else{
					return 0;
				}
			}else if(sortType==SORT_SMALL){
				long v=file1.length() - file2.length();
				if(v>1){
					return 1;
				}else if(v<1){
					return -1;
				}else{
					return 0;
				}
			}else{
				return 0;
			}
			
		}
		
	}


	/*
	public  class RepaintFigure extends Thread{
		
		public void run(){
			rootFigure.repaint();
			rootFigure.validate();
			rootFigure.getParent().validate();
			log.info(rootFigure.getParent());
			log.info("repaint:");
			canvas.redraw();
		}
	}
	public class ThreadPaint extends Thread{
		public void run(){
			PlatformUI.getWorkbench().getDisplay().syncExec(new RepaintFigure());
			
		}
	}
	*/
	public void clearList(){
		actionValueList.removeAll(actionValueList);
		rootFigure.removeAll();
		rootFigure.repaint();
		
		//Thread t1=new ThreadPaint();
		//t1.setPriority(Thread.MAX_PRIORITY);
		//t1.run();
		//rootFigure.repaint();
		//PlatformUI.getWorkbench().getDisplay().syncExec(new RepaintFigure());
		//TODO:why didn't paint.
		/*
		try {
			Thread.sleep(1000*5);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}*/
	}
	public void initList(File file) {
		
		//re init
		explorerFigure = new Explorer();
		explorerFigure.setBackgroundColor(ColorConstants.white);
		explorerFigure.add(new MoveUpPrevNextFigure("", moveUpPrevImage));
		explorerFigure.setLayoutManager(new CustomFlowLayout(canvas,rootFigure));
		
		ImageLoader imageLoader = new ImageLoader();
		
		//add flv files
		String flvfiles[] = getFLVFiles(file);
		for (int i = 0; i < flvfiles.length; i++) {
			File f = new File(flvfiles[i]);

			String name = FileNameUtils.getRemovedExtensionName(f.getName());
			ThumbnailFigure th = new ThumbnailFigure(name,
					loadingImage);
			if (!f.getName().toLowerCase().endsWith(".flv")) {
				log.info("no extension");
				th.setHasExtension(false);
			}
			//log.trace(th.getLabel()+","+th.isHasExtension());
			explorerFigure.add(th);
			imageLoader.add(th, f);
		}

		//add mp4 files ? option?
		//add flv files
		String ex=Akj_betasPlugin.getDefault().getPluginPreferences().getString(FLVToolsPage.SUPPORTED_EXTENSIONS);
		if(ex.length()>0){
		String mp4files[] = getExtensionFiles(file,ex.split(" "));
		for (int i = 0; i < mp4files.length; i++) {
			File f = new File(mp4files[i]);

			String name = FileNameUtils.getRemovedExtensionName(f.getName());
			ThumbnailFigure th = new ThumbnailFigure(name,
					loadingImage);
			th.setExtension(FileNameUtils.getExtension(f.getName()));
			explorerFigure.add(th);
			imageLoader.add(th, f);
		}
		}
		// add folders
		String list[] = file.list();
		if(list!=null){
		for (int i = 0; i < list.length; i++) {
			if (new File(file, list[i]).isDirectory()) {
				FolderFigure folder=new FolderFigure(list[i], folderImage);
				//test
				
				explorerFigure.add(folder);
			}
		}
		}

		rootFigure.add(explorerFigure);

		Thread t = new Thread(imageLoader);
		t.start();
		// scroll.setMinSize(320,136*parent.getChildren().length);
	}
	
	

	/*
	 * public Composite createFileInfoComposite(Composite parent,File file){
	 * Composite panel=new Composite(parent,SWT.NULL); GridLayout grid=new
	 * GridLayout(2,false); panel.setLayout(grid);
	 * 
	 * Label imgLabel=new Label(panel,SWT.NULL);
	 * imgLabel.setImage(loadIcon(file)); GridData data1=new GridData();
	 * data1.verticalSpan=2; imgLabel.setLayoutData(data1);
	 * 
	 * 
	 * CCombo fileName=new CCombo(panel,SWT.NULL);
	 * 
	 * fileName.add(trimExtension(file.getName())); for(int i=0;i<assistantNames.length;i++){
	 * fileName.add(assistantNames[i]); } fileName.select(0);
	 * 
	 * GridData data2=new GridData(GridData.FILL_HORIZONTAL);
	 * data2.minimumWidth=160; fileName.setLayoutData(data2);
	 * 
	 * 
	 * CCombo box=makeComboBox(panel);
	 * 
	 * GridData data3=new GridData(GridData.FILL_HORIZONTAL);
	 * data3.minimumWidth=160; box.setLayoutData(data3);
	 * 
	 * ActionValues values=new ActionValues(file,box,fileName);
	 * actionValueList.add(values); imgLabel.addMouseListener(values); return
	 * panel; }
	 */

	/*
	private String trimExtension(String name) {
		int e = name.toLowerCase().lastIndexOf(".flv");
		if (e != -1) {
			return name.substring(0, e);
		}
		return name;
	}
	*/

	private String[] folders;

	private void initFolder(File file) {
		String list[] = file.list();
		if(list==null){
			list=new String[0];
		}
		ArrayList array = new ArrayList();
		for (int i = 0; i < list.length; i++) {
			if (new File(file, list[i]).isDirectory()) {
				array.add(list[i]);
			}
		}
		
		folders = (String[]) array.toArray(new String[0]);

	}

	private CCombo makeComboBox(Composite panel) {
		CCombo box = new CCombo(panel, SWT.READ_ONLY);
		box.add("");
		// File file=new File(findBaseDir());
		for (int i = 0; i < folders.length; i++) {
			box.add(folders[i]);
		}

		return box;
	}

	private void hookContextMenu() {
		MenuManager menuMgr = new MenuManager("#PopupMenu");
		menuMgr.setRemoveAllWhenShown(true);
		menuMgr.addMenuListener(new IMenuListener() {
			public void menuAboutToShow(IMenuManager manager) {
				ExplorerView.this.fillContextMenu(manager);
			}
		});

	}

	private void contributeToActionBars() {
		IActionBars bars = getViewSite().getActionBars();
		fillLocalPullDown(bars.getMenuManager());
		fillLocalToolBar(bars.getToolBarManager());
	}

	private void fillLocalPullDown(IMenuManager manager) {
		// manager.add(action1);

	}

	private void fillContextMenu(IMenuManager manager) {
		// manager.add(action1);

	}

	private void fillLocalToolBar(IToolBarManager manager) {
		// manager.add(action1);

	}

	ArrayList actionValueList = new ArrayList();

	private FigureCanvas canvas;

	private Figure rootFigure;

	private FlowPlayerShell flowPlayerShell;

	private MenuItem convert;

	public class ActionValues implements MouseListener {
		private File file;

		private CCombo combo;

		private CCombo text;

		public File getFile() {
			return file;
		}

		public String getNewName() {
			return text.getText();
		}

		public String getNewDirectory() {
			return combo.getText();
		}

		public void setEnabled(boolean bool) {
			combo.setEnabled(bool);
			text.setEnabled(bool);
		}

		public ActionValues(File file, CCombo combo, CCombo text) {
			this.file = file;
			this.combo = combo;
			this.text = text;
		}

		public void mouseDoubleClick(MouseEvent e) {
			log.warn("mouse");

		}

		public void mouseDown(MouseEvent e) {
			// TODO Auto-generated method stub

		}

		public void mouseUp(MouseEvent e) {
			// TODO Auto-generated method stub

		}
	}

	public void openDirectory() {
		DirectoryDialog dialog = new DirectoryDialog(PlatformUI.getWorkbench()
				.getActiveWorkbenchWindow().getShell());
		String path = dialog.open();
		if (path != null) {
			openDirectory(path);
		}
	}

	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {

		canvas.forceFocus();
	}

	public void startExecute(File files[]){
		
		getProgressMonitor().beginTask(Messages.getString("converting"),files.length);
		convert.setEnabled(false);
		enableseek.setEnabled(false);
		renameFile.setEnabled(false);
	}
	public void finishExecute() {
		
		ffmpegExecuter=null;
		//
		convert.setEnabled(true);
		enableseek.setEnabled(true);//
		renameFile.setEnabled(true);
		
	}
	
	
	
	private int executingIndex;

	private Explorer explorerFigure;

	private MenuItem enableseek;

	private MenuItem renameFile;

	private MenuItem movePaths;

	private Menu moveDirMenu;
	private Menu movePathMenu;

	private MenuItem pspMenuItem;

	private MenuItem mpegMenuItem;

	private MenuItem wmvMenuItem;

	private MenuItem aviMenuItem;

	private MenuItem mp3MenuItem;

	private MenuItem wavMenuItem;
	public void executingFile(File file,int index){
		log.info("executingFile:"+index);
		executingIndex=index;
		
		if(convertingDialog!=null && convertingDialog.isOpened()){
			log.info("update:"+executingIndex);
			convertingDialog.updateSelect(executingIndex);
		}
	}

	
	public IProgressMonitor getProgressMonitor() {
		WorkbenchWindow workbenchWindow = (WorkbenchWindow)PlatformUI.getWorkbench().getActiveWorkbenchWindow();
		return workbenchWindow.getStatusLineManager().getProgressMonitor();
	}

	public void cancel() {
		if(ffmpegExecuter!=null){
			ffmpegExecuter.cancel();
		}
	}
	
	public class DropOpen implements DropFileListener{

		public void dropFile(String[] path) {
			for (int i = 0; i < path.length; i++) {
				
				File file=new File(path[i]);//open first one.
				if(file.isFile()){
					openDirectory(file.getParentFile().getAbsolutePath());
				}else{
					openDirectory(file.getAbsolutePath());
				}
				break;
			}
			
		}
		
	}
	
	public class YoutubeDownloaded implements YoutubeDLListener{

		public void downloaded(String path) {
			reload();
		}
		
	}
	
	
	
}